package SGLisp

import (
	//"fmt"
	"strconv"

	. "git.oschina.net/yangdao/SGLisp/parse"
)

type IFucntion interface {
	Exec([]Node, *Context) Node
}

type NativeFunction struct {
	MyFunction  func([]Node, *Context) Node
	FunctionExt func([]Node, *Context) Node
}

func (this *NativeFunction) Exec(lst []Node, context *Context) Node {
	if this.FunctionExt == nil {
		return this.MyFunction(lst[1:], context)
	}
	return this.FunctionExt(lst, context)
}
func (n *NativeFunction) Position() *Pos {
	return nil
}
func (this *NativeFunction) Type() int {
	return NodeType_NativeFunction
}

func (n *NativeFunction) String() string {
	return "NativeFunction"
}
func (this *NativeFunction) HashCode() interface{} { return this }

func (n *NativeFunction) Children() []Node {
	return nil
}

func ExecFunc(this interface{}, args []Node, ctx *Context) Node {
	switch this.(type) {
	case *NativeFunction:
		return this.(*NativeFunction).Exec(args, ctx)
	case *FunctionNode:
		return ExecSGLispFunc(this.(*FunctionNode), args, ctx)
	}
	return nil
}

func ExecSGLispFunc(this *FunctionNode, args []Node, ctx *Context) Node {
	funcCtx := NewContext(ctx)
	if args != nil {
		if this.VecArgsNode != nil {
			for i := 0; i < len(this.VecArgsNode.Children()); i++ {
				SymName := this.VecArgsNode.Children()[i].(*SymbolNode).Val
				funcCtx.Define(SymName, args[i])
			}
		} else {
			for i := 0; i < len(args); i++ {
				var SymName string
				if i == 0 {
					SymName = "%"
				} else {
					SymName = strconv.Itoa(i+1) + "%"
				}
				funcCtx.Define(SymName, args[i])
			}
		}
	}
	return Evaluate(this.ListNode, funcCtx)
}
